; void normalizar_local_asm (
; 	unsigned char *src,		RDI
; 	unsigned char *dst,		RSI
; 	int h,					RDX		Altura de la imagen
; 	int w,					RCX		Ancho de la imagen
; 	int row_size			R8
; );

%define src rdi
%define dst rsi
%define h rdx
%define w rcx
%define row_size r8


global normalizar_local_asm

normalizar_local_asm:
	push rbp
	mov rbp, rsp
	push r10
	push r11
	push r12
	push r13	;Contador filas
	push r14	;contador columnas
	push r15
	
	xor r13, r13
	xor r14, r14

	push rdx	;guardo h
	mov r9, 16
	xor rax, rax
	xor rdx, rdx
	mov eax, r8d
	sub rax, 2
	idiv r9		;en RAX tengo la cantidad de veces que cicla Columna Coeficiente
	mov r12, rdx	;en RDX tengo el resto, la cantidad de elementos que no se pueden operar de a 16
	add r12, 1
	
	mov r9, rax
	
	pop rdx	;restauro "h"


	xor r10, r10 	;contador de ciclo de filas
	mov r10, rdx
	sub r10, 2		;tengo en r10 la cantidad de filas a procesar
	
	add src, r8		;Sumo tam_linea para dejar en blanco la 1er linea
	add dst, r8
	
	add src, 1		;Sumo 1 para dejar en blanco la 1er columna
	add dst, 1
	
	;src->RDI - dst->RSI - h->RDX - w->RCX, row_size->r8
.cicloF:

	mov r11, r9	;contador de ciclo de columnas dec de a 1.
	
	.cicloC:	 
		movdqu xmm0, [src]		;Muevo el source al registro
		movdqu xmm15, xmm0		;Me hago una copia del valor original
		
		
		

		
		
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  MAXIMOS y MINIMOS  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

;MAXMIN:		;MAX (rdi->src, rsi->fila, rdx->columna, rcx->ancho)
	
	;HUBICO LOS PIXELES EN XMM
	xor rax, rax					;ACA "FILA" ES EL CONTADOR DE CICLOS DE LA FILA,
									;COLUMNA TMB ES EL CONTADOR DE CICLOS
									;"ANCHO" - PENSARLO.
	
;	mov eax, ecx	;muevo el ancho a rax
;	mul rsi			;como rsi tiene un int (4 bytes) el resultado entero va a entrar en r8
	mov r15, src		;en r15 tengo src
;	add r15, rax		;r15-> src+fila*ancho
;	add r15, rdx		;r15-> src + fila*ancho + columna	CENTRO
	sub r15, row_size		;esta en el pixel de arriba del centro
	sub r15, 1		;esta arriba a la izquierda
	movdqu xmm0, [r15]	;tengo la punta superior izquierda
	add r15, 1		
	movdqu xmm1, [r15]	;medio superior
	add r15, 1
	movdqu xmm2, [r15]		;punta superior derecha
	add r15, r8		; l sumo el ancho de la imagen
	movdqu xmm3, [r15]	;centro derecho
	sub r15, 1
	movdqu xmm4, [r15]	;centro
	sub r15, 1
	movdqu xmm5, [r15]	;centro izquierdo
	add r15, r8		;Le sumo el ancho de la imagen
	movdqu xmm6, [r15]	;punta izquierda inferior
	add r15, 1
	movdqu xmm7, [r15]	;centro inferior
	add r15, 1	
	movdqu xmm8, [r15]	;punta derecha inferior
	;CALCULO MAXIMOS
	movdqu xmm9, xmm0
	
	pminub xmm9, xmm1	;MAX y MIN entre Arriba-Izquierda y Arriba-Medio
	pmaxub xmm0, xmm1
	
	pminub xmm9, xmm2	;MAX y MIN entre Anterior y Arriba-Derecha
	pmaxub xmm0, xmm2
	pminub xmm9, xmm3	;MAX y MIN entre Anterior y Medio-Derecha
	pmaxub xmm0, xmm3
	pminub xmm9, xmm4	;MAX y MIN entre Anterior y Centro
	pmaxub xmm0, xmm4
	pminub xmm9, xmm5	;MAX y MIN entre Anterior y Medio-Izquierda
	pmaxub xmm0, xmm5
	pminub xmm9, xmm6	;MAX y MIN entre Anterior y Abajo-Izquierda
	pmaxub xmm0, xmm6
	pminub xmm9, xmm7	;MAX y MIN entre Anterior y Abajo-Medio
	pmaxub xmm0, xmm7
	pminub xmm9, xmm8	;MAX y MIN entre Anterior y Abajo-Derecha
	pmaxub xmm0, xmm8

	movdqu xmm4, xmm9	;MAX en XMM0 y MIN en XMM4
	



	pxor xmm14, xmm14
	;%%%%%%%%%%%%%%%%%%%%%%%%%%%  MAXIMOS  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	
	movdqu xmm1, xmm0	;Me guardo una copia de los 16pixels levantados para desempaquetar.
	punpckhbw xmm1, xmm14	;XMM1 = 15|14|13|12|11|10|09|08 -- Desenpaqueto la parte alta de Byte a Word
	punpcklbw xmm0, xmm14	;XMM0 = 07|06|05|04|03|02|01|00 -- Desenpaqueto la parte Baja de Byte a Word
	
	movdqu xmm2, xmm0		;Copio ambos para desempaquetar a 32 bits
	movdqu xmm3, xmm1

	punpckhwd xmm3, xmm14	;XMM3 = 15|14|13|12
	punpcklwd xmm1, xmm14	;XMM1 = 11|10|09|08

	punpckhwd xmm2, xmm14	;XMM2 = 07|06|05|04
	punpcklwd xmm0, xmm14	;XMM0 = 03|02|01|00
	
	cvtdq2ps xmm3, xmm3		;Convierto a Float
	cvtdq2ps xmm1, xmm1
	cvtdq2ps xmm2, xmm2
	cvtdq2ps xmm0, xmm0

;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  MINIMOS  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	movdqu xmm5, xmm4	;Me guardo una copia de los 16pixels levantados para desempaquetar.
	punpckhbw xmm5, xmm14	;XMM5 = 15|14|13|12|11|10|09|08 -- Desenpaqueto la parte alta de Byte a Word
	punpcklbw xmm4, xmm14	;XMM4 = 07|06|05|04|03|02|01|00 -- Desenpaqueto la parte Baja de Byte a Word
	
	movdqu xmm6, xmm4		;Copio ambos para desempaquetar a 32 bits
	movdqu xmm7, xmm5

	punpckhwd xmm7, xmm14	;XMM7 = 15|14|13|12
	punpcklwd xmm5, xmm14	;XMM5 = 11|10|09|08

	punpckhwd xmm6, xmm14	;XMM6 = 07|06|05|04
	punpcklwd xmm4, xmm14	;XMM4 = 03|02|01|00

	cvtdq2ps xmm7, xmm7
	cvtdq2ps xmm5, xmm5
	cvtdq2ps xmm6, xmm6
	cvtdq2ps xmm4, xmm4
	
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  ORIGINALES  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	movdqu xmm9, xmm15	;Me guardo una copia de los 16pixels levantados para desempaquetar.
	punpckhbw xmm9, xmm14	;XMM9 = 15|14|13|12|11|10|09|08 -- Desenpaqueto la parte alta de Byte a Word
	punpcklbw xmm8, xmm14	;XMM8 = 07|06|05|04|03|02|01|00 -- Desenpaqueto la parte Baja de Byte a Word
	
	movdqu xmm10, xmm8		;Copio ambos para desempaquetar a 32 bits
	movdqu xmm11, xmm9

	punpckhwd xmm11, xmm14	;XMM11 = 15|14|13|12
	punpcklwd xmm9, xmm14	;XMM9 = 11|10|09|08

	punpckhwd xmm10, xmm14	;XMM10 = 07|06|05|04
	punpcklwd xmm8, xmm14	;XMM8 = 03|02|01|00

	cvtdq2ps xmm11, xmm11
	cvtdq2ps xmm9, xmm9
	cvtdq2ps xmm10, xmm10
	cvtdq2ps xmm8, xmm8
	
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  OPERACIONES  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	divps xmm11, xmm3	;Src/Max - 15|14|13|12
	divps xmm9, xmm1	;Src/Max - 11|10|09|08
	divps xmm10, xmm2	;Src/Max - 07|06|05|04
	divps xmm8, xmm0	;Src/Max - 03|02|01|00
	
	addps xmm11, xmm7	;Src/Max + Min - 15|14|13|12
	addps xmm9, xmm5	;Src/Max + Min - 11|10|09|08
	addps xmm10, xmm6	;Src/Max + Min - 07|06|05|04
	addps xmm8, xmm4	;Src/Max + Min - 03|02|01|00
	;Paso de Float a Entero con signo
	cvtps2dq xmm11, xmm11	
	cvtps2dq xmm9, xmm9
	cvtps2dq xmm10, xmm10
	cvtps2dq xmm8, xmm8
							;Paso de signed int Packed DoubleWord a Word
	packssdw xmm8, xmm10	;xmm8 = 07|06|05|04|03|02|01|00
	packssdw xmm9, xmm11	;xmm9 = 15|14|13|12|11|10|09|08
							;Paso de signed int Word a Unsigned Byte con saturacion
	packuswb xmm8, xmm9		;xmm8 = 15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00
	
	movdqu xmm0, xmm8

;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  FIN DE LAS OPERACIONES  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
		
		movdqu [dst], xmm0		;muevo los datos al destino
		add src, 16				;src
		add dst, 16				;dst
		add r14, 16				;Contador para saber en que columna estoy.
		dec r11				;contador C
		cmp r11, 0
		jne .cicloC
		
		mov r11, r12		;Si termine restauro el contador de columnas al contador de las q se procesan de a 1
		dec r11
		
.sigue:			;aca paso los pixeles que me quedaron sin procesar
	cmp r11, 0
	je .prepCF			;Si es 0, restauro las variables de los contadores
	cmp r11, 4
	jge .deACuatro			;Si los que quedan por procesar con 4 o mas, los proceso de a 4

	xor rax, rax
	mov rax, 4
	sub rax, r11			;Resto a 4 los que quedan por procesar (Que son menos de 4)
	sub src, rax			;Resto el resultado anterio al Src, Dst y lo sumo al contador de columnas
	sub dst, rax			;Esto me va a dar r11 = 4, y va a correr Src y Dst los lugares necesarios para
	add r11, rax			;Procesar las ultimas 4 columnas
	jmp .sigue
	
;	xor rax, rax
;	mov al, [src]
;	mov [dst], al
;	add src, 1
;	add dst, 1
;	sub r11, 1
;	jmp .sigue


.deACuatro:
	mov r15, src
					;MUEVO A REGISTROS XMM CONVIRTIENDO A DWORD
	sub r15, row_size		;esta en el pixel de arriba del centro
	sub r15, 1		;esta arriba a la izquierda
	pmovzxbd xmm0, [r15]	;tengo la punta superior izquierda
	add r15, 1		
	pmovzxbd xmm1, [r15]	;medio superior
	add r15, 1
	pmovzxbd xmm2, [r15]		;punta superior derecha
	add r15, r8		; l sumo el ancho de la imagen
	pmovzxbd xmm3, [r15]	;centro derecho
	sub r15, 1
	pmovzxbd xmm4, [r15]	;centro
	movdqu xmm10, xmm4			;Me Guardo el centro para operar despues
	sub r15, 1
	pmovzxbd xmm5, [r15]	;centro izquierdo
	add r15, r8		;Le sumo el ancho de la imagen
	pmovzxbd xmm6, [r15]	;punta izquierda inferior
	add r15, 1
	pmovzxbd xmm7, [r15]	;centro inferior
	add r15, 1	
	pmovzxbd xmm8, [r15]	;punta derecha inferior
	
	movdqu xmm9, xmm0

	pminud xmm9, xmm1	;MAX y MIN entre Arriba-Izquierda y Arriba-Medio
	pmaxud xmm0, xmm1
	
	pminud xmm9, xmm2	;MAX y MIN entre Anterior y Arriba-Derecha
	pmaxud xmm0, xmm2
	pminud xmm9, xmm3	;MAX y MIN entre Anterior y Medio-Derecha
	pmaxud xmm0, xmm3
	pminud xmm9, xmm4	;MAX y MIN entre Anterior y Centro
	pmaxud xmm0, xmm4
	pminud xmm9, xmm5	;MAX y MIN entre Anterior y Medio-Izquierda
	pmaxud xmm0, xmm5
	pminud xmm9, xmm6	;MAX y MIN entre Anterior y Abajo-Izquierda
	pmaxud xmm0, xmm6
	pminud xmm9, xmm7	;MAX y MIN entre Anterior y Abajo-Medio
	pmaxud xmm0, xmm7
	pminud xmm9, xmm8	;MAX y MIN entre Anterior y Abajo-Derecha
	pmaxud xmm0, xmm8

	movdqu xmm4, xmm9	;MAX en XMM0 y MIN en XMM4
	;Convierto a Float
	cvtdq2ps xmm4, xmm4	;MIN
	cvtdq2ps xmm0, xmm0	;MAX
	cvtdq2ps xmm10, xmm10	;CENTRO (ORIGINAL - SRC)
	
	;Opero
	divps xmm10, xmm0	;Src/Max
	addps xmm10, xmm4
	
	;Convierto a Entero
	cvtps2dq xmm10, xmm10

	packssdw xmm10, xmm10	;Empaqueto a Word entero con signo
	packuswb xmm10, xmm10	;Empaqueto a Byte entero sin signo
	
		
	movd [dst], xmm10
	add src, 4
	add dst, 4
	sub r11, 4
	jmp .sigue
	
	
.prepCF:	;aca preparo el cicloFilas
	dec r10
	cmp r10, 0
	je .fin
	add src, 2
	add dst, 2
	jmp .cicloF
	
	
.fin:
	pop r15
	pop r14
	pop r13
	pop r12
	pop r11
	pop r10
	pop rbp
	ret
	
